# coding=utf-8

import os
import json
import datetime
from urllib.request import urlopen
from urllib.request import Request
from urllib.error import URLError
from urllib.parse import urlencode
from urllib.parse import quote_plus
from api.mylogger import logger


class DemoError(Exception):
    pass


class TTS:
    def __init__(self, content_text, person, speed, pitch, volume) -> None:
        # avatarsever
        # self.API_KEY = 'Snfh9oEBu6lsVRKhyOfTzZPp'
        # self.SECRET_KEY = 'nrX4TupvNbLay8skCtezxxq0MEQeQpvW'

        # laohuang
        self.API_KEY = 'GfImrFCiXoGuy9WW5QP7nGrP'
        self.SECRET_KEY = 'yEqjPKBdakzFv0ldyQQV7RVNbZtqRl0d'

        self.TEXT = content_text

        # 发音人选择, 基础音库：0为度小美，1为度小宇，3为度逍遥，4为度丫丫，
        # 精品音库：5为度小娇，103为度米朵，106为度博文，110为度小童，111为度小萌，默认为度小美 
        self.PER = person
        # 语速，取值0-15，默认为5中语速
        self.SPD = speed
        # 音调，取值0-15，默认为5中语调
        self.PIT = pitch
        # 音量，取值0-9，默认为5中音量
        self.VOL = volume
        # 下载的文件格式, 3：mp3(default) 4： pcm-16k 5： pcm-8k 6. wav
        self.AUE = 3

        self.FORMATS = {3: "mp3", 4: "pcm", 5: "pcm", 6: "wav"}
        self.FORMAT = self.FORMATS[self.AUE]
        self.CUID = "123456PYTHON"
        self.TTS_URL = 'http://tsn.baidu.com/text2audio'
        self.TOKEN_URL = 'http://aip.baidubce.com/oauth/2.0/token'
        self.SCOPE = 'audio_tts_post'  # 有此scope表示有tts能力，没有请在网页里勾选

    def __del__(self):
        pass

    def fetch_token(self):
        params = {
            'grant_type': 'client_credentials',
            'client_id': self.API_KEY,
            'client_secret': self.SECRET_KEY
        }
        post_data = urlencode(params)
        post_data = post_data.encode('utf-8')
        req = Request(self.TOKEN_URL, post_data)
        try:
            f = urlopen(req, timeout=5)
            result_str = f.read()
        except URLError as err:
            logger.info('token http response http code : ' + str(err.code))
            result_str = err.read()
        result_str = result_str.decode()

        result = json.loads(result_str)
        if 'access_token' in result.keys() and 'scope' in result.keys():
            if not self.SCOPE in result['scope'].split(' '):
                return '', 401, 'scope is not correct'
            # logger.info('SUCCESS WITH TOKEN: %s ; EXPIRES IN SECONDS: %s' % (result['access_token'], result['expires_in']))
            return result['access_token'], 0, 'success'
        else:
            return '', 401, 'MAYBE API_KEY or SECRET_KEY not correct: access_token or scope not found in token response'

    def text2audio(self, audio_path, audio_short_filename):
        token, code, msg = self.fetch_token()
        if code != 0:
            logger.error(f"fetch_token失败,msg is {msg}")
            return '', 400, 'fetch_token失败'

        tex = quote_plus(self.TEXT)  # 此处TEXT需要两次urlencode
        params = {
            'tok': token,
            'tex': tex,
            'per': self.PER,
            'spd': self.SPD,
            'pit': self.PIT,
            'vol': self.VOL,
            'aue': self.AUE,
            'cuid': self.CUID,
            'lan': 'zh',
            'ctp': 1,  # lan ctp 固定参数
        }
        data = urlencode(params)
        req = Request(self.TTS_URL, data.encode('utf-8'))
        has_error = False
        try:
            f = urlopen(req)
            result_str = f.read()
            headers = dict((name.lower(), value) for name, value in f.headers.items())
            has_error = ('content-type' not in headers.keys() or headers['content-type'].find('audio/') < 0)
            if has_error:
                errdata = json.loads(result_str.decode('utf8'))
                logger.info('has error:' + errdata['err_msg'])
        except URLError as err:
            logger.info('asr http response http code : ' + str(err.code))
            result_str = err.read()
            errdata = json.loads(result_str.decode('utf8'))
            has_error = True

        if has_error:
            with open(os.path.join(audio_path, 'error.txt'), 'wb') as of:
                of.write(result_str)
            return '', 400, errdata['err_msg']

        audio_filename_with_path = audio_path + "/" + audio_short_filename
        with open(audio_filename_with_path, 'wb') as of:
            of.write(result_str)

        return audio_filename_with_path, 0, 'success'


if __name__ == '__main__':
    TEXT = '你好，这是一个测试'
    tts = TTS(TEXT, 0, 5, 5, 5)
    audio_url, _, _ = tts.text2audio()
    logger.info(audio_url)
